﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.IO;

namespace CavinatorService.DAO.Extensao
{
    public static class Extensao
    {
        #region Atributos

        static CultureInfo culture;

        #endregion

        #region Construtor

        /// <summary>
        /// Construtor padrão
        /// </summary>
        static Extensao()
        {
            culture = new CultureInfo("pt-BR");
        }

        #endregion

        #region Métodos
        /// <summary>
        /// Método que verifica se um DataRow contém uma determinada coluna
        /// </summary>
        /// <typeparam name="T">Tipo de retorno que a coluna deveria conter</typeparam>
        /// <param name="drLinha">DataRow a ser examinado</param>
        /// <param name="strNome">Noma da coluna que deveria estar contida no DataRow</param>
        /// <param name="valorPadrao">Valor padrão de retorno, caso drLinha não esteja contida no DataRow ou tenha um valor nulo</param>
        /// <returns>Retorna o valor da coluna do tipo informado se não for nulo, se não retorna o valor padrão</returns>
        public static T VerificarColuna<T>(this DataRow drLinha, string strNome, T valorPadrao)
        {
            if (drLinha.Table.Columns.Contains(strNome) && drLinha[strNome] != null && !(drLinha[strNome] is DBNull))
            {
                TypeConverter tcConversor = TypeDescriptor.GetConverter(typeof(T));

                return (T)tcConversor.ConvertFrom(null, culture, Convert.ToString(drLinha[strNome], culture));
            }
            else
                return valorPadrao;
        }

        /// <summary>
        /// Método que verifica de uma linha apontada pelo SqlDataReader contém uma determinada coluna e se seu valor não é nulo
        /// </summary>
        /// <typeparam name="T">Tipo de retorno que a coluna deveria conter</typeparam>
        /// <param name="sdrLinha">SqlDataReader a ser examinado</param>
        /// <param name="strNome">Noma da coluna que deveria estar contida no SqlDataReader</param>
        /// <param name="valorPadrao">Valor padrão de retorno, caso sdrLinha não esteja contida no DataRow ou tenha um valor nulo</param>
        /// <returns>Retorna o valor da coluna do tipo informado se não for nulo, se não retorna o valor padrão</returns>
        public static T VerificarColuna<T>(this IDataReader sdrLinha, string strNome, T valorPadrao)
        {
            if (!(sdrLinha[strNome] is DBNull))
            {
                TypeConverter tcConversor = TypeDescriptor.GetConverter(typeof(T));


                return (T)tcConversor.ConvertFrom(null, culture, Convert.ToString(sdrLinha[strNome], culture));
            }

            return valorPadrao;
        }


        /// <summary>
        /// Método que verifica se existe uma coluna no DataRow
        /// </summary>
        /// <param name="drLinha">DataRow com as informações</param>
        /// <param name="strNome">Nome da coluna</param>
        /// <returns>Se existe ou não</returns>
        public static bool VerificaExistencia(this DataRow drLinha, string strNome)
        {
            return (drLinha.Table.Columns.Contains(strNome) && drLinha[strNome] != null && !(drLinha[strNome] is DBNull));
        }

        /// <summary>
        /// Método que verifica se existe uma coluna no SqlDataReader
        /// </summary>
        /// <param name="drLinha">DataRow com as informações</param>
        /// <param name="strNome">Nome da coluna</param>
        /// <returns>Se existe ou não</returns>
        public static bool VerificaExistencia(this IDataReader sdrLinha, string strNome)
        {
            sdrLinha.GetSchemaTable().DefaultView.RowFilter = string.Format("ColumnName= '{0}'", strNome);
            return (sdrLinha.FieldCount > 0 && sdrLinha.GetSchemaTable().DefaultView.Count > 0 && sdrLinha[strNome] != null && !(sdrLinha[strNome] is DBNull));
        }

        /// <summary>
        /// Lista de Objetos
        /// </summary>
        /// <typeparam name="T">Tipo da Classe</typeparam>
        /// <param name="reader">Retorno do Banco</param>
        /// <returns>Lista de Objetos populados</returns>
        private static List<T> CriarListaObjeto<T>(this IDataReader reader) where T : class , new()
        {
            List<T> lst = new List<T>();

            while (reader.Read())
                lst.Add((T)Activator.CreateInstance(typeof(T), reader));

            reader.Close();

            return lst;
        }

        public static List<T> CriarListaObjeto<T>(this IDataReader reader, string campoId, string campoNome) where T : class , new()
        {
            List<T> lst = new List<T>();

            try
            {
                while (reader.Read())
                    lst.Add((T)Activator.CreateInstance(typeof(T), reader, campoId, campoNome));
            }
            catch
            {
                //TODO:Tratar erro
            }
            finally
            {
                reader.Close();
            }


            return lst;
        }

        /// <summary>
        /// Cria um objeto
        /// </summary>
        /// <typeparam name="T">Tipo da Classe</typeparam>
        /// <param name="reader">Retorno do banco</param>
        /// <returns>Objeto populado</returns>
        public static T CriarObjeto<T>(this IDataReader reader) where T : class , new()
        {
            if (reader.Read())
            {
                T instancia = null;

                try
                {
                    instancia = (T)Activator.CreateInstance(typeof(T), reader);
                }
                catch
                {

                }
                finally
                {
                    reader.Close();
                }

                return instancia;
            }

            return new T();
        }

        public static T CriarObjeto<T>(this IDataReader reader, string campoId, string campoNome) where T : class , new()
        {
            if (reader.Read())
            {
                T instancia = null;

                try
                {
                    instancia = (T)Activator.CreateInstance(typeof(T), reader, campoId, campoNome);
                }
                catch
                {
                    //TODO:Tratar erro
                }
                finally
                {
                    reader.Close();
                }

                reader.Close();
                return instancia;
            }

            return new T();
        }

        public static void Load<T>(this DataTable dt, IEnumerable<T> collection, string columnName = "")
        {
            dt.Columns.Clear();

            dt.Columns.Add(columnName, typeof(T));

            if (collection != null)
            {
                foreach (T value in collection)
                {
                    dt.Rows.Add(value);
                }
            }
        }

        public static bool EstaArquivoDisponivel(string arquivo)
        {
            FileStream stream = null;

            try
            {
                stream = File.Open(arquivo, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
            }
            catch (IOException)
            {
                return false;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }

            return true;
        }

        #endregion
    }
}
